package destinychild;

import aoshiScript.entity.IWuNa;
import com.alibaba.fastjson.JSONObject;
import commons.entity.Constant;
import commons.entity.NativeCp;
import commons.util.*;
import destinychild.entity.DcPointInfo;
import destinychild.entity.DcTask;
import destinychild.entity.SimoLocation;
import destinychild.entity.TaskInfo;
import fgoScript.entity.PointColor;
import fgoScript.exception.AppNeedRestartException;
import fgoScript.exception.AppNeedStopException;
import fgoScript.exception.AppNeedUpdateException;
import fgoScript.exception.AppNeedNextException;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.awt.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author RENZHEHAO
 * @version 1.0.0
 * @ClassName DaillyMission.java
 * @Description 每日任务自动执行实体
 * @createTime 2019年11月06日 11:56:00
 */
public class DaillyMission implements Runnable{
    private static final Logger LOGGER = LogManager.getLogger(DaillyMission.class);
    private ThreadPoolTaskExecutor circleTPExcutor;
    private boolean flag = false;
    private IWuNa wuna;
    private IModule light;
    private DcPointInfo dcPointInfo;
    private DcTask dcTask;
    private boolean ifrestart;
    private int vpnCounts = 1;
    private TaskInfo tempTaskInfo;
    private IModule module;
    private final DcPointInfo DC_POINTINFO = DcPointInfo.getSpringBean();
    public static DaillyMission getSpringBean(){
        return (DaillyMission) MySpringUtil.getApplicationContext().getBean("daillyMission");
    }
    public void daillyMissionStart(boolean ifMin) throws AppNeedStopException {
        String accountStr = PropertiesUtil.getValueFromFileNameAndKey("account_" + NativeCp.getUserName(), "DCinit", Constant.DC + "/");
        int[] accounts = GameUtil.strToIntArray(accountStr,false);
        int size = accounts.length;
        int account;
        for (int i = 0; i < size; i++) {
            account = accounts[i];
            getDcTask(true, account, ifMin);
            if(dcTask == null){
                LOGGER.error("该dctask描述文件不存在！");
                continue;
            }
            openDC(account);
            startOneAccount(account, ifMin);
        }
        boolean ifCloseComputter = Boolean.parseBoolean(PropertiesUtil.getValueFromFileNameAndKey("IF_CLOSE_COMPUTER", "DCinit", Constant.DC + "/"));
        if ("RZH_SERVER".equals(NativeCp.getUserName()) && ifMin && ifCloseComputter) {
            ProcessDealUtil.closeComputerInTime(2);
        }
    }
    private void startOneAccount(int account, boolean ifMin) throws AppNeedStopException {
        // main线程：执行主要日常任务。
        goMainMission(account, ifMin);
        ProcessDealUtil.closeLD(account);
    }
    private void goMainMission(int account, boolean ifMin) throws AppNeedStopException {
        List<TaskInfo> taskInfoList = dcTask.getTasklist();
        /** 任务列表大小 **/
        int size = taskInfoList.size();
        LOGGER.info("任务列表个数位为" + size);
        int times = 0;
        for (int i = 0; i < size && isFlag(); i++) {

            try {
                startOneMission(i, account, times, isIfrestart());
                times = 0;
            } catch (AppNeedRestartException e) {
                if ("通信中断".equals(e.getName())){
//                    vpnCounts++;
                }
                LOGGER.error(e.getMessage(),e);
                i--;
                times++;
                setIfrestart(true);
                openDC(account);
                continue;
            } catch (AppNeedNextException e) {
                LOGGER.error(e.getMessage(),e);
                setIfrestart(true);
                openDC(account);
                continue;
            } catch (AppNeedStopException e){
                LOGGER.error(e.getMessage(),e);
            } finally {
                getDcTask(true, account, ifMin);
            }

        }
    }
    private boolean ifDoMissionByWeekDaysAndHours(String exceptWekkDaysHours) throws Exception{
        if(StringUtils.isBlank(exceptWekkDaysHours)){
            return true;
        }
        String[] WeekDayHours = exceptWekkDaysHours.split("_");
        String[] WeekDays = WeekDayHours[0].split(",");
        int[] Hours = getHours(WeekDayHours[1].split(","));
        Calendar cd = Calendar.getInstance();
        Date nowDate = new Date();
        cd.setTime(nowDate);
        int hourOfDay = cd.get(Calendar.HOUR_OF_DAY);
        String WekkOfDay = GameUtil.getWeek(nowDate)+ "";

        int wL = WeekDays.length;
        for (int i = 0; i < wL; i++) {
            if(WekkOfDay.equals(WeekDays[i]) &&
                    (Hours[0] <= hourOfDay && Hours[1] > hourOfDay)
                ){
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println(StringUtils.isBlank("   "));
    }
    private int[] getHours(String[] hourStr){
        int hl = hourStr.length;
        int[] intHours= new int[hl];
        for (int i = 0; i < hl; i++) {
            intHours[i]= Integer.parseInt(hourStr[i]);
        }
        return intHours;
    }
    public void startOneMission(int index, int account,int times, boolean ifRestart) throws AppNeedRestartException, AppNeedNextException, AppNeedStopException {
        if (ifRestart && index != 0){
            startOneMission(0,account, times, false);
            setIfrestart(false);
        }
//        if(!tempTaskInfo.isCheckSmallHome() && times == 1 ){
//            LOGGER.info("未到达任务页面位置，该任务忽略，任务可能完成一半，直接跳到下一任务！");
//            throw new AppNeedNextException();
//        }
        Point taskReturnPoint = dcTask.getTaskReturnPoint();
        String accountStr = PropertiesUtil.getValueFromFileNameAndKey("returnMaxCount", "DCinit", Constant.DC + "/");
        int returnMaxcount = Integer.valueOf(accountStr);
        /** 重复次数 **/
        int repeat;
        /** 返回点击次数 **/
        int returnCount;
        /** 单个任务点击点集合（点） **/
        List<Point> tempTaskClickPoints;
        /** 单个任务点击点集合（色） **/
        List<Color> tempTaskClickColors;
        /** 单个任务点击点集合 大小 **/
        int clickPointsSize;
        int clickColorsSize;
        Point temPoint;
        Color tempColor;
        String exceptWekkDaysHours;
        setFlag(true);
        wuna.setAllStop(false);
        String startModuleName;
        tempTaskInfo = dcTask.getTasklist().get(index);
        exceptWekkDaysHours = tempTaskInfo.getExceptWekkDaysHours();
        /** 如果未启用就不执行 **/
        if (!tempTaskInfo.isEnable()){
            LOGGER.info("任务名称：" + tempTaskInfo.getTaskName() + " 任务未启用，跳过");
            return;
        }
        /** 根据星期和时间判断是否执行执行 **/
        boolean ifDo = true;
        try {
            ifDo = ifDoMissionByWeekDaysAndHours(exceptWekkDaysHours);
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            LOGGER.error("解析exceptWekkDaysHours错误，默认执行！");
        }
        if (!ifDo){
            LOGGER.info("任务名称：" + tempTaskInfo.getTaskName() + " 任务在该时段不启用，跳过");
            return;
        }
        repeat = tempTaskInfo.getTaskPointRepetitions();
        LOGGER.info("开始执行任务： " + tempTaskInfo.getTaskName());
        tempTaskClickPoints = tempTaskInfo.getTaskClickPoints();
        tempTaskClickColors = tempTaskInfo.getTaskClickColors();
        clickPointsSize = tempTaskClickPoints.size();
        clickColorsSize = tempTaskClickColors.size();
        if (clickPointsSize > 0) {
            /** 进入任务场景 **/
            LOGGER.info("进入任务场景");
            try {
                wuna.alwaysClickForStrategy("" + tempTaskInfo.getTaskName()+"_into", 50, false, false,
                        true,false,tempTaskInfo.getTaskInToDelaySeconds(), Constant.DC + "/" + account + "/" , tempTaskInfo);
            } catch (AppNeedRestartException e) {
                if(!tempTaskInfo.isCheckSmallHome()){
                    LOGGER.info("未到达任务页面位置，该任务忽略，任务可能完成一半，直接跳到下一任务！");
                    throw new AppNeedNextException();
                }else{
                    throw e;
                }
            }
            // 检测第一次脚本的结果页面，
            if (!GameUtil.likeEqualColor(
                                            tempTaskInfo.getMissionPc().getColor(),
                                            GameUtil.getScreenPixel(tempTaskInfo.getMissionPc().getPoint())
                                        )
                ){
                // 是否抛出异常后，直接进行下抛异常
                if(tempTaskInfo.isCheckSmallHome() || times == 0 ){
                    LOGGER.info("未到达任务页面位置，重新启动！");
                    throw new AppNeedRestartException();
                }else{
                    LOGGER.info("未到达任务页面位置，该任务忽略，任务可能完成一半，直接跳到下一任务！");
                    throw new AppNeedNextException();
                }
            }else {
            }
            /** 遍历单任务 点击点，执行点击 **/
            for (int k = 0; k < repeat && isFlag(); k++) {
                for (int j = 0; j < clickPointsSize && isFlag(); j++) {
                    temPoint = tempTaskClickPoints.get(j);
                    tempColor = GameUtil.getScreenPixel(temPoint);
                    if (clickColorsSize > 0 ) {
                        if(GameUtil.likeEqualColor(tempColor, tempTaskClickColors.get(j))){
                            GameUtil.getMymouse().mouseMoveByPoint(temPoint,true,true);

                            GameUtil.getMymouse().mousePressAndRelease(50);

                        }else{
                            continue;
                        }
                    } else {
                        GameUtil.getMymouse().mouseMoveByPoint(temPoint,true,true);


                        GameUtil.getMymouse().mousePressAndRelease(50);

                    }
                    //检测网络不稳定
                    for (int i = 0; i < 100; i++) {
                        GameUtil.delay(1000);
                        if (GameUtil.likeEqualColor(GameUtil.getScreenPixel(DC_POINTINFO.getLoading().getPoint()),
                                                    DC_POINTINFO.getLoading().getColor(),10)){
                            LOGGER.info("进度圈等待中！延后5秒执行脚本");
                            GameUtil.delay(5000);
                        } else {
                            break;
                        }
                    }
                    startModuleName = tempTaskInfo.getStartModleName();
                    if (!"".equals(startModuleName)){
                        module = (IModule) MySpringUtil.getApplicationContext().getBean(startModuleName);
                        module.start();
                    } else {
                        wuna.alwaysClickForStrategy("" + tempTaskInfo.getTaskName()+"_click", 500, false,true,
                                true,false,
                                tempTaskInfo.getTaskAutoClickDelaySeconds(),
                                Constant.DC + "/" + account + "/", tempTaskInfo);
                    }
                    if (tempTaskInfo.isSmallReturn()){
                        GameUtil.getMymouse().mouseMoveByPoint(taskReturnPoint,true,true);


                        GameUtil.getMymouse().mousePressAndRelease(50);

                    }
                    GameUtil.delay(5000);
                }
            }
        } else {
            wuna.alwaysClickForStrategy("" + tempTaskInfo.getTaskName()+"_click", 50, false, false,
                    true,true,tempTaskInfo.getTaskInToDelaySeconds(),
                    Constant.DC + "/" + account + "/", tempTaskInfo);
        }
        returnCount = 0;
        //设置返回脚本
        if(tempTaskInfo.isReturnTopScript()){
            LOGGER.info("执行返回脚本！");
            /** 设定自动点击最大延时 **/
            wuna.alwaysClickForStrategy("" + tempTaskInfo.getTaskName()+"_return", 50, false, false,
                    true, false,tempTaskInfo.getTaskReturnDelaySeconds(),
                    Constant.DC + "/" + account + "/", tempTaskInfo);
        }
        //如果没有到达任务首页，进行返回
        while (tempTaskInfo.isReturnTop() && isFlag() && !GameUtil.likeEqualColor(GameUtil.getScreenPixel(dcTask.getTaskPagePoint()),dcTask.getTaskPageColor())){
            //检测HOME主页
            if (GameUtil.likeEqualColor(GameUtil.getScreenPixel(dcTask.getHomePagePoint()),dcTask.getHomePageColor())){
                GameUtil.getMymouse().mouseMoveByPoint(dcTask.getIntoTaskPoint(),true,true);


                GameUtil.getMymouse().mousePressAndRelease(50);

            }else{
                GameUtil.getMymouse().mouseMoveByPoint(taskReturnPoint,true,false);

                GameUtil.getMymouse().mousePressAndRelease(50);

            }
            GameUtil.delay(5000);
            //超次数设定
            if (returnCount++ > returnMaxcount) {
                LOGGER.error("返回任务页面失败！");
                throw new AppNeedRestartException();
            }
        }
        ThreadUtil.waitUntilNoneThread(circleTPExcutor);
        LOGGER.info("任务： " + tempTaskInfo.getTaskName() + " 执行完了！");
    }
    public void openDC(int account) throws AppNeedStopException {
        ProcessDealUtil.killAllDnPlayer();
        if(vpnCounts % 2 == 0){
            ProcessDealUtil.startTencentXriver(account);
        }else{
            ProcessDealUtil.startDC(account);
        }
        moveToDestinyPoint(account);
        // laowangAccelerate
        if(vpnCounts % 2 == 0){
            GameUtil.delay(30*1000);
            try {
                wuna.alwaysClickForStrategy("" + "laoWang_into", 50, false, false,
                        true,false,45, Constant.DC + "/" + account + "/" , tempTaskInfo);
            } catch (AppNeedRestartException e) {
                e.printStackTrace();
            }
            ProcessDealUtil.startDCWithOutClose(account);
        }

    }
    public void daillyMissionStop(){
        wuna.setGO(false);
        wuna.setAllStop(true);
        GameUtil.setSTOP_SCRIPT(true);
        if (null != module){
            try {
                module.stop();
            } catch (AppNeedRestartException e) {
                LOGGER.error(e.getMessage());
            }
        }
    }
    private void moveToDestinyPoint(int account) throws AppNeedStopException {
        SimoLocation simoLocation = SimoLocation.getInstance();
        List<PointColor> pocoList = new ArrayList<PointColor>();
        pocoList.add(new PointColor(simoLocation.getTargetPCList().get(0).getPoint(), simoLocation.getTargetPCList().get(0).getColor(),true));
        try {
            GameUtil.waitUntilOneColor(pocoList, Constant.DCMonitor);
        } catch (AppNeedUpdateException e) {
            LOGGER.error(e.getMessage(),e);
        } catch (AppNeedRestartException e) {
            openDC(account);
            LOGGER.error(e.getMessage(),e);
            return;
        } catch (AppNeedStopException e) {
            LOGGER.error(e.getMessage(),e);
        }
        simoLocation.moveToDestinyPoint();
    }
    public void toggle(Boolean ifMin) throws AppNeedStopException {
        if (!isFlag()){
            LOGGER.info("启动每日脚本");
            setFlag(true);
            daillyMissionStart(ifMin);
            setFlag(false);
        }else{
            LOGGER.info("关闭每日脚本");
            daillyMissionStop();
            try {
                ThreadUtil.waitUntilNoneThread(circleTPExcutor);
            } catch (AppNeedRestartException e) {
                LOGGER.error(e.getMessage(),e);
            }
            setFlag(false);
        }
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public void setCircleTPExcutor(ThreadPoolTaskExecutor circleTPExcutor) {
        this.circleTPExcutor = circleTPExcutor;
    }

    public void setWuna(IWuNa wuna) {
        this.wuna = wuna;
    }

    public DcTask getDcTask(boolean reload,int account, boolean ifMin) {
        if (reload || dcTask == null) {
            String filepath = NativeCp.getUserDir() + "/config/"+ Constant.DC +"/"+ account +"/" +"dcTask_"+NativeCp.getUserName()+".json";
            if (ifMin){
                filepath = NativeCp.getUserDir() + "/config/"+ Constant.DC +"/"+ account +"/" +"dcTask_min_"+NativeCp.getUserName()+".json";
            }
            LOGGER.info("JSON路径为： " + filepath);
            dcTask = JSONObject.parseObject(GameUtil.getJsonString(filepath), DcTask.class);
        }
        return dcTask;
    }


    public void setLight(IModule light) {
        this.light = light;
    }

    public void setDcPointInfo(DcPointInfo dcPointInfo) {
        this.dcPointInfo = dcPointInfo;
    }

    public boolean isIfrestart() {
        return ifrestart;
    }

    public void setIfrestart(boolean ifrestart) {
        this.ifrestart = ifrestart;
    }

    public DcPointInfo getDcPointInfo() {
        DcPointInfo dpi = DcPointInfo.getInstance();
        return dpi;
    }


    @Override
    public void run() {
        try {
            toggle(true);
        } catch (AppNeedStopException e) {
            e.printStackTrace();
        }
    }
}
